﻿using System;
using System.IO;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Text;

namespace HooIzDat.Web.Helpers
{
    public static class HtmlHelperExtensions
    {
        public static IHtmlString CssReferences(this HtmlHelper html, bool firstIsMinimisedPath, params string[] paths)
        {
            var sb = new StringBuilder();
            RenderCssReferences(html, text => sb.AppendLine(text), firstIsMinimisedPath, paths);
            return new HtmlString(sb.ToString());
        }

        public static void RenderCssReferences(this HtmlHelper html, bool firstIsMinimisedPath, params string[] paths)
        {
            var response = html.ViewContext.HttpContext.Response;
            RenderCssReferences(html, text => response.Write(text), firstIsMinimisedPath, paths);
        }

        private static void RenderCssReferences(this HtmlHelper html, Action<string> renderCallback, bool firstIsMinimisedPath, params string[] paths)
        {
            if (html == null || paths == null || paths.Length == 0)
                return;

            var template = "<link href=\"{0}\" rel=\"stylesheet\" type=\"text/css\" />";
            var debug = html.ViewContext.HttpContext.IsDebuggingEnabled;
            var server = html.ViewContext.HttpContext.Server;
            
            string src = "";

            if (!debug && firstIsMinimisedPath) // Release mode with minimised stylesheet
            {
                // Use minimised stylesheet path
                src = paths[0];
                if (VirtualPathUtility.IsAppRelative(src))
                {
                    src = VirtualPathUtility.ToAbsolute(src);
                }
                renderCallback(string.Format(template, src));
            }
            else
            {
                foreach (var path in firstIsMinimisedPath ? paths.Skip(1) : paths)
                {
                    src = path;
                    var fileName = VirtualPathUtility.GetFileName(src);

                    if (VirtualPathUtility.IsAppRelative(src))
                    {
                        src = VirtualPathUtility.ToAbsolute(src);
                    }
                    renderCallback(string.Format(template, src));
                }
            }
        }

        public static IHtmlString ScriptReferences(this HtmlHelper html, bool firstIsCombinedPath, params string[] paths)
        {
            var sb = new StringBuilder();
            RenderScriptReferences(html, text => sb.AppendLine(text), firstIsCombinedPath, paths);
            return new HtmlString(sb.ToString());
        }

        public static void RenderScriptReferences(this HtmlHelper html, params string[] paths)
        {
            RenderScriptReferences(html, false, paths);
        }

        public static void RenderScriptReferences(this HtmlHelper html, bool firstIsCombinedPath, params string[] paths)
        {
            var response = html.ViewContext.HttpContext.Response;
            RenderScriptReferences(html, text => response.Write(text), firstIsCombinedPath, paths);
        }

        private static void RenderScriptReferences(this HtmlHelper html, Action<string> renderCallback, bool firstIsCombinedPath, params string[] paths)
        {
            if (html == null || paths == null || paths.Length == 0)
                return;

            var template = "<script type=\"text/javascript\" src=\"{0}\"></script>";
            var debug = html.ViewContext.HttpContext.IsDebuggingEnabled;
            var server = html.ViewContext.HttpContext.Server;
            string src = "";

            if (!debug && firstIsCombinedPath) // Release mode with combined script
            {
                // Use combined script path
                src = paths[0];
                if (VirtualPathUtility.IsAppRelative(src))
                {
                    src = VirtualPathUtility.ToAbsolute(src);
                }
                renderCallback(string.Format(template, src));
            }
            else
            {
                foreach (var path in firstIsCombinedPath ? paths.Skip(1) : paths)
                {
                    src = path;
                    var fileName = VirtualPathUtility.GetFileName(src);

                    if (VirtualPathUtility.IsAppRelative(src))
                    {
                        src = VirtualPathUtility.ToAbsolute(src);

                        if (debug && !src.EndsWith(".debug.js", StringComparison.InvariantCultureIgnoreCase)) // Debug mode
                        {
                            if (!fileName.StartsWith("jquery"))
                            {
                                var debugSrc = Path.ChangeExtension(src, ".debug.js");
                                if (File.Exists(server.MapPath(debugSrc)))
                                {
                                    src = debugSrc;
                                }
                            }
                        }
                        else if (!debug) // Release mode
                        {
                            if (fileName.StartsWith("jquery", StringComparison.InvariantCultureIgnoreCase) &&
                                !fileName.EndsWith(".min.js"))
                            {
                                var minSrc = Path.ChangeExtension(src, ".min.js");
                                if (File.Exists(server.MapPath(minSrc)))
                                {
                                    src = minSrc;
                                }
                            }
                        }
                    }

                    renderCallback(string.Format(template, src));
                }
            }
        }
    }
}